using System.Globalization;
using Engine;
using Game;
using GameEntitySystem;
using TemplatesDatabase;

namespace SCIENEW {
    public class ComponentExCraftingTable : ComponentCraftingTable, IElectricElementCrafterComponent {
        public new string[] m_matchedIngredients = new string[36];
        public static int RequiredHeatLevel => 0;

        public int? RequireItemSlotIndex { get; set; } = null;

        public override int GetSlotCapacity(int slotIndex, int value) {
            if (slotIndex < SlotsCount - 2) {
                return base.GetSlotCapacity(slotIndex, value);
            }
            return 0;
        }

        public override void AddSlotItems(int slotIndex, int value, int count) {
            Base_AddSlotItems(slotIndex, value, count);
            if (slotIndex != ResultSlotIndex) m_slots[ResultSlotIndex].Count = 0;
            Task.Run(UpdateCraftingResult);
        }

        public override int RemoveSlotItems(int slotIndex, int count) {
            int num = 0;
            if (slotIndex == ResultSlotIndex) {
                if (m_matchedRecipe != null) {
                    if (m_matchedRecipe.RemainsValue != 0
                        && m_matchedRecipe.RemainsCount > 0) {
                        if (m_slots[RemainsSlotIndex].Count == 0
                            || m_slots[RemainsSlotIndex].Value == m_matchedRecipe.RemainsValue) {
                            int num2 = BlocksManager.Blocks[Terrain.ExtractContents(m_matchedRecipe.RemainsValue)].GetMaxStacking(m_matchedRecipe.RemainsValue) - m_slots[RemainsSlotIndex].Count;
                            count = MathUtils.Min(count, num2 / m_matchedRecipe.RemainsCount * m_matchedRecipe.ResultCount);
                        }
                        else {
                            count = 0;
                        }
                    }
                    count = count / m_matchedRecipe.ResultCount * m_matchedRecipe.ResultCount;
                    int value = GetSlotValue(ResultSlotIndex);
                    num = Base_RemoveSlotItems(slotIndex, count);
                    if (num > 0) {
                        for (int i = 0; i < 36; i++) {
                            if (!string.IsNullOrEmpty(m_matchedIngredients[i])) {
                                int index = (i % 6) + (m_craftingGridSize * (i / 6));
                                m_slots[index].Count = MathUtils.Max(m_slots[index].Count - (num / m_matchedRecipe.ResultCount), 0);
                            }
                        }
                        if (m_matchedRecipe.RemainsValue != 0
                            && m_matchedRecipe.RemainsCount > 0) {
                            m_slots[RemainsSlotIndex].Value = m_matchedRecipe.RemainsValue;
                            m_slots[RemainsSlotIndex].Count += num / m_matchedRecipe.ResultCount * m_matchedRecipe.RemainsCount;
                        }
                        ComponentPlayer componentPlayer = FindInteractingPlayer();
                        if (componentPlayer != null
                            && componentPlayer.PlayerStats != null) {
                            componentPlayer.PlayerStats.ItemsCrafted += num;
                            Project.FindSubsystem<SubsystemTechTree>(true).Unlock(value, componentPlayer);
                        }
                    }
                }
            }
            else {
                m_slots[ResultSlotIndex].Count = 0;
                num = Base_RemoveSlotItems(slotIndex, count);
            }
            Task.Run(UpdateCraftingResult);
            return num;
        }

        public override void Load(ValuesDictionary valuesDictionary, IdToEntityMap idToEntityMap) {
            base.Load(valuesDictionary, idToEntityMap);
            m_craftingGridSize = (int)MathF.Sqrt(SlotsCount - 2);
            Task.Run(UpdateCraftingResult);
        }

        public override void UpdateCraftingResult() {
            int num = int.MaxValue;
            for (int i = 0; i < m_craftingGridSize; i++) {
                for (int j = 0; j < m_craftingGridSize; j++) {
                    int num2 = i + (j * 6);
                    int slotIndex = i + (j * m_craftingGridSize);
                    int slotValue = GetSlotValue(slotIndex);
                    int slotCount = GetSlotCount(slotIndex);
                    if (slotCount > 0) {
                        m_matchedIngredients[num2] = IECraftingRecipesManager.BlockToIngredient(slotValue);
                        num = MathUtils.Min(num, slotCount);
                    }
                    else {
                        m_matchedIngredients[num2] = null;
                    }
                }
            }
            ComponentPlayer componentPlayer = FindInteractingPlayer();
            float playerLevel = componentPlayer?.PlayerData.Level ?? 1f;
            CraftingRecipe craftingRecipe = MatchRecipe(Project.FindSubsystem<SubsystemTerrain>(throwOnError: true), m_matchedIngredients, 0f, playerLevel);
            if (craftingRecipe != null
                && craftingRecipe.ResultValue != 0) {
                m_matchedRecipe = craftingRecipe;
                m_slots[ResultSlotIndex].Value = craftingRecipe.ResultValue;
                m_slots[ResultSlotIndex].Count = craftingRecipe.ResultCount * num;
            }
            else {
                m_matchedRecipe = null;
                m_slots[ResultSlotIndex].Value = 0;
                m_slots[ResultSlotIndex].Count = 0;
            }
            if (craftingRecipe != null
                && !string.IsNullOrEmpty(craftingRecipe.Message)) {
                string message = craftingRecipe.Message;
                if (message.StartsWith("[")
                    && message.EndsWith("]")) {
                    message = LanguageControl.Get("CRMessage", message.Substring(1, message.Length - 2));
                }
                componentPlayer?.ComponentGui.DisplaySmallMessage(message, Color.White, blinking: true, playNotificationSound: false);
            }
        }

        public int Base_RemoveSlotItems(int slotIndex, int count) //ComponentInventoryBase的RemoveSlotItems方法
        {
            if (slotIndex < 0
                || slotIndex >= this.m_slots.Count)
                return 0;
            Slot slot = this.m_slots[slotIndex];
            count = MathUtils.Min(count, this.GetSlotCount(slotIndex));
            slot.Count -= count;
            return count;
        }

        public void Base_AddSlotItems(int slotIndex, int value, int count) {
            if (count <= 0
                || slotIndex < 0
                || slotIndex >= this.m_slots.Count)
                return;
            ComponentInventoryBase.Slot slot = this.m_slots[slotIndex];
            if (this.GetSlotCount(slotIndex) != 0 && this.GetSlotValue(slotIndex) != value
                || this.GetSlotCount(slotIndex) + count > this.GetSlotCapacity(slotIndex, value))
                throw new InvalidOperationException("Cannot add slot items.");
            slot.Value = value;
            slot.Count += count;
        }

        public CraftingRecipe MatchRecipe(SubsystemTerrain terrain, string[] ingredients, float heatLevel, float playerLevel) => IECraftingRecipesManager.FindMatchingRecipe(Project.FindSubsystem<SubsystemTerrain>(throwOnError: true), m_matchedIngredients, 0f, playerLevel);
    }
}